package com.neu.credit.creditscore.service.parking.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.neu.credit.creditscore.common.utils.*;
import com.neu.credit.creditscore.dto.req.ParkingPreOrderInfoReq;
import com.neu.credit.creditscore.dto.res.parking.*;
import com.neu.credit.creditscore.entity.CreditScore;
import com.neu.credit.creditscore.entity.Transmissionjson;
import com.neu.credit.creditscore.entity.books.Books;
import com.neu.credit.creditscore.entity.hospital.Fees;
import com.neu.credit.creditscore.entity.parking.ParkingAppointments;
import com.neu.credit.creditscore.entity.parking.ParkingFees;
import com.neu.credit.creditscore.entity.parking.ParkingLots;
import com.neu.credit.creditscore.entity.parking.ParkingSpaces;
import com.neu.credit.creditscore.mapper.CreditScoreMapper;
import com.neu.credit.creditscore.mapper.TransmissionjsonMapper;
import com.neu.credit.creditscore.mapper.parking.ParkingAppointmentsMapper;
import com.neu.credit.creditscore.mapper.parking.ParkingFeesMapper;
import com.neu.credit.creditscore.mapper.parking.ParkingLotsMapper;
import com.neu.credit.creditscore.mapper.parking.ParkingSpacesMapper;
import com.neu.credit.creditscore.service.KafkaProducerService;
import com.neu.credit.creditscore.service.parking.ParkingLotsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;
import org.zachary.commonmodule.entity.MqTransmissionJson;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 停车场信息表 服务实现类
 * </p>
 *
 * @author baomidou
 * @since 2025-06-14
 */
@Slf4j
@Service
public class ParkingLotsServiceImpl extends ServiceImpl<ParkingLotsMapper, ParkingLots> implements ParkingLotsService {

    @Autowired
    private ParkingLotsMapper parkingLotsMapper;

    @Autowired
    private TransmissionjsonMapper transmissionjsonMapper;

    @Autowired
    private ParkingSpacesMapper parkingSpacesMapper;

    @Autowired
    private ParkingAppointmentsMapper parkingAppointmentsMapper;

    @Autowired
    private ParkingFeesMapper parkingFeesMapper;
    @Autowired
    private CreditScoreMapper creditScoreMapper;
    private static final Integer ServiceType_ConvenientParking=9;
    @Autowired
    private KafkaProducerService kafkaProducerService;
    @Override
    public Result<List<ParkingLotsSimpleInfoRes>> getRecommendParking() {
        try {

            LambdaQueryWrapper<ParkingLots> parkingLotsQuery = new LambdaQueryWrapper<>();
            parkingLotsQuery.orderByDesc(ParkingLots::getLeftCount);
            List<ParkingLots> parkingLots = parkingLotsMapper.selectList(parkingLotsQuery);

            if (CollectionUtils.isEmpty(parkingLots)) {
                return Result.success(new ArrayList<>());
            }

            List<ParkingLotsSimpleInfoRes> resList = parkingLots.stream().map(lot -> {
                ParkingLotsSimpleInfoRes res = new ParkingLotsSimpleInfoRes();
                res.setId(lot.getId());
                res.setTitle(lot.getParkingLotName());
                res.setLocation(lot.getParkingLotLocation());
                res.setLeftCount(lot.getLeftCount());
                return res;
            }).collect(Collectors.toList());

            return Result.success(resList);

        } catch (Exception e) {
            log.error("getRecommendParking has a error", e);
            return Result.error("获取推荐停车场失败！");
        }
    }

    @Override
    public Result<ParkingLotsTypeRes> getParkingByType(int pageNum, int pageSize, int type, String title) {
        try {
            LambdaQueryWrapper<ParkingLots> parkQuery = new LambdaQueryWrapper<>();
            parkQuery.eq(ParkingLots::getParkingLotType, type)
                    .like(!title.equals(""), ParkingLots::getParkingLotName, title);

            Page<ParkingLots> page = new Page<>(pageNum, pageSize);
            Page<ParkingLots> parkingLotsPage = parkingLotsMapper.selectPage(page, parkQuery);

            List<ParkingLots> records = parkingLotsPage.getRecords();

            List<ParkingLotsInfoRes> parkingList = records.stream().map(lot -> {
                ParkingLotsInfoRes res = new ParkingLotsInfoRes();
                res.setId(lot.getId());
                res.setTitle(lot.getParkingLotName());
                res.setLocation(lot.getParkingLotLocation());
                res.setLeftCount(lot.getLeftCount());
                res.setTotalCount(lot.getTotalSpaces());
                res.setPrice(lot.getPrice());
                res.setImage(lot.getImage());
                res.setTag(lot.getParkingLotType().toString());
                return res;
            }).collect(Collectors.toList());

            int total = (int) parkingLotsPage.getTotal();

            return Result.success(new ParkingLotsTypeRes(total, parkingList));


        } catch (Exception e) {
            log.error("getParkingByType has a error pageNum={}, pageSize={}, type = {}, title={}", pageNum, pageSize, type, title, e);
            return Result.error("获取停车场失败！");
        }
    }

    @Override
    public Result<List<ParkingSpaces>> getSpaces(int lotId) {
        try {

            if (lotId == 0) {
                log.error("param is null lotId={}", lotId);
                return Result.error("获取失败！");
            }

            LambdaQueryWrapper<ParkingSpaces> spaceQuery = new LambdaQueryWrapper<>();
            spaceQuery.eq(ParkingSpaces::getParkingLotId, lotId);
            List<ParkingSpaces> parkingSpaces = parkingSpacesMapper.selectList(spaceQuery);

            if (CollectionUtils.isEmpty(parkingSpaces)){
                log.error("param has a error lotId={}", lotId);
                return Result.error("获取失败！");
            }

            return Result.success(parkingSpaces);

        } catch (Exception e) {
            log.error("getSpaces has a error lotId={}", lotId, e);
            return Result.error("获取车位信息失败！");
        }
    }

    @Override
    public Result<ParkingLots> getParkingLotInfoById(int lotId) {
        try {
            if (lotId == 0) {
                log.error("param is null lotId={}", lotId);
                return Result.error("获取失败！");
            }

            ParkingLots parkingLots = parkingLotsMapper.selectById(lotId);
            if (ObjectUtils.isEmpty(parkingLots)){
                log.error("param has a error lotId={}", lotId);
                return Result.error("获取失败！");
            }

            return Result.success(parkingLots);

        }catch (Exception e){
            log.error("getParkingLotInfoById has a error lotId={}", lotId, e);
            return Result.error("获取停车场信息失败！");
        }
    }

    @Override
    public Result<ParkingPreOrderInfoRes> savePreOrderInfo(ParkingPreOrderInfoReq req,Integer userId) {
        try {
            long currentTime = System.currentTimeMillis();
            long startTime = req.getStartTime();
            long timeDiff = startTime - currentTime;

            if (timeDiff > 1800000) {
                return Result.error("您预约的时间距离开始使用时间较晚，请临期再预约");
            }
            ParkingAppointments appointments = new ParkingAppointments();
            appointments.setParkingLotId(req.getLotId());
            appointments.setSpaceNum(req.getSpaceNum());
            appointments.setStartTime(new Date(req.getStartTime()));
            appointments.setEndTime(new Date(req.getEndTime()));
            appointments.setUserId(userId);
            appointments.setAppointmentStatus(ParkingAppointments.PREORDER);
            appointments.setAppointmentNumber("APPT" + System.currentTimeMillis() + String.format("%04d", ThreadLocalRandom.current().nextInt(10000)));


            parkingAppointmentsMapper.insert(appointments);

            ParkingPreOrderInfoRes res = new ParkingPreOrderInfoRes();
            ParkingLots parkingLots = parkingLotsMapper.selectById(req.getLotId());
            res.setParkingLotName(parkingLots.getParkingLotName());
            res.setSpaceNum(req.getSpaceNum());
            String startTimeStr = DateUtils.formatTime(appointments.getStartTime());
            String endTimeStr = DateUtils.formatTime(appointments.getEndTime());
            res.setAppointTimeStr(startTimeStr + "--" + endTimeStr);
            long spendTime = req.getEndTime() - req.getStartTime();

            int spendHour = (int) Math.ceil((double) spendTime / (1000 * 60 * 60));
            int totalPrice = spendHour * parkingLots.getPrice();
            res.setPrice(parkingLots.getPrice());
            res.setTotalPrice(totalPrice);
            res.setSpendTimeCount(spendHour);
            res.setAppointmentId(appointments.getId());

            return Result.success(res);


        }catch (Exception e){
            log.error("savePreOrderInfo has a error req={}", JSONObject.toJSONString(req), e);
            return Result.error("获取停车场信息失败！");
        }
    }

    @Override
    public Result<String> orderParking(int appointmentId,Integer userId) {
        try {

            CreditScore creditScore = creditScoreMapper.selectById(userId);
            Integer score = creditScore.getScore();

            if (score <= 300){
                return Result.success("下单失败！信用积分不足！");
            }

            ParkingAppointments appointments = parkingAppointmentsMapper.selectById(appointmentId);
            appointments.setAppointmentStatus(ParkingAppointments.PREORDER);
            // 3. 更新停车位状态（关键改进点）
            // 构建查询条件
            LambdaQueryWrapper<ParkingSpaces> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ParkingSpaces::getParkingLotId, appointments.getParkingLotId())
                    .eq(ParkingSpaces::getSpaceNumber, appointments.getSpaceNum());

// 执行查询
            ParkingSpaces spaces = parkingSpacesMapper.selectOne(queryWrapper);
            spaces.setSpaceStatus(ParkingSpaces.APPOINT);
            parkingSpacesMapper.updateById(spaces );
            ParkingLots parkingLot = parkingLotsMapper.selectById(spaces.getParkingLotId());
            parkingLot.setLeftCount(parkingLot.getLeftCount()-1);
            parkingLotsMapper.updateById(parkingLot);

            RandomIdGenerator generator = new RandomIdGenerator();
            String num = generator.generateUniqueId();

            appointments.setAppointmentNumber(num);

            parkingAppointmentsMapper.updateById(appointments);


            return Result.success("下单成功");
        }catch (Exception e){
            log.error("orderParking has a error appointmentId={}", appointmentId, e);
            return Result.error("获取停车场信息失败！");
        }
    }
    @Component // 确保被Spring容器扫描并管理
    public class ParkingAppointmentExpireTask {

        @Autowired
        private ParkingAppointmentsMapper appointmentsMapper;

        @Autowired
        private ParkingSpacesMapper parkingSpacesMapper;
        @Autowired
        private TransmissionjsonMapper transmissionjsonMapper;

        @Autowired
        private ParkingLotsMapper parkingLotsMapper;

        @Autowired
        private KafkaProducerService kafkaProducerService;

        private static final Integer ServiceType_ConvenientParking = 9; // 与主服务保持一致

        // 项目启动时执行一次（依赖注入完成后）
        @PostConstruct
        public void initCheck() {
            log.info("项目启动，触发预约未使用检查任务");
            checkAndHandleExpiredAppointments();
        }

        // 每天凌晨3点执行（避开业务高峰期）
        @Scheduled(cron = "0 0 3 * * ?")
        public void scheduledCheck() {
            log.info("定时任务触发，开始检查逾期未使用的预约");
            checkAndHandleExpiredAppointments();
        }

        /**
         * 检查并处理逾期未使用的预约
         */
        public void checkAndHandleExpiredAppointments() {
            try {
                // 1. 查询状态为“已预约”且结束时间已过期的订单
                LambdaQueryWrapper<ParkingAppointments> query = new LambdaQueryWrapper<>();
                query.eq(ParkingAppointments::getAppointmentStatus, ParkingAppointments.PREORDER) // 已预约但未使用
                        .lt(ParkingAppointments::getEndTime, new Date()); // 结束时间早于当前时间
                List<ParkingAppointments> expiredAppointments = appointmentsMapper.selectList(query);

                if (expiredAppointments.isEmpty()) {
                    log.info("无逾期未使用的预约记录");
                    return;
                }

                // 2. 批量处理逾期订单
                for (ParkingAppointments appointment : expiredAppointments) {
                    // 2.1 更新预约状态为“逾期未使用”
                    appointment.setAppointmentStatus(ParkingAppointments.OVERDUE_UNUSED);
                    appointment.setUpdatedAt(new Date());
                    appointmentsMapper.updateById(appointment);

                    // 2.2 释放锁定的车位（恢复为空闲状态）
                    LambdaQueryWrapper<ParkingSpaces> spaceQuery = new LambdaQueryWrapper<>();
                    spaceQuery.eq(ParkingSpaces::getParkingLotId, appointment.getParkingLotId())
                            .eq(ParkingSpaces::getSpaceNumber, appointment.getSpaceNum());
                    ParkingSpaces space = parkingSpacesMapper.selectOne(spaceQuery);
                    if (space != null && space.getSpaceStatus() == ParkingSpaces.APPOINT) {
                        space.setSpaceStatus(ParkingSpaces.FREE); // 恢复为空闲
                        parkingSpacesMapper.updateById(space);

                        // 2.3 同步更新停车场剩余车位数量
                        ParkingLots parkingLot = parkingLotsMapper.selectById(appointment.getParkingLotId());
                        parkingLot.setLeftCount(parkingLot.getLeftCount() + 1); // 释放一个车位
                        parkingLotsMapper.updateById(parkingLot);
                    }
                    String currentUuid = appointment.getId().toString()+"parking";

                    // 1. 检查transmissionjson表中是否已存在相同UUID
                    LambdaQueryWrapper<Transmissionjson> transmissionjsonquery = new LambdaQueryWrapper<>();
                    transmissionjsonquery.eq(Transmissionjson::getUuid, currentUuid);
                    Transmissionjson existing = transmissionjsonMapper.selectOne(transmissionjsonquery);

                    // 2. 如果已存在相同UUID，跳过发送逻辑
                    if (existing != null) {
                        continue; // 直接进入下一次循环
                    }

                    // 3. 不存在则插入transmissionjson并发送Kafka消息
                    Transmissionjson transmissionjson = new Transmissionjson();
                    transmissionjson.setUuid(currentUuid);
                    transmissionjson.setDueTime(Date.from(appointment.getEndTime().toInstant()));
                    transmissionjsonMapper.insert(transmissionjson);

                    // 2.4 发送信用分扣减消息（预约未使用扣减信用分）
                    sendCreditScoreMessage(appointment);
                }

                log.info("预约未使用检查完成，共处理 {} 条逾期记录", expiredAppointments.size());

            } catch (Exception e) {
                log.error("处理逾期未使用预约时发生错误", e);
            }
        }

        /**
         * 发送信用分调整消息（扣减积分）
         */
        private void sendCreditScoreMessage(ParkingAppointments appointment) {
            MqTransmissionJson json = new MqTransmissionJson();
            json.setUuid(appointment.getId().toString()+"parking");
            json.setUserId(appointment.getUserId());
            json.setServiceType(ServiceType_ConvenientParking);
            json.setPaid(true); // 未产生支付行为
            json.setOverdue(true); // 标记为逾期未使用
            json.setOverduePeriod(-1);
            json.setAmount(-1); // 无费用
            json.setDesc("便捷停车信用分计算");
            json.setFinishTime(null);
            json.setDueTime(appointment.getEndTime().toInstant()); // 逾期时间为预约结束时间

            kafkaProducerService.sendJsonMessage(json);
            log.info("已发送信用分调整消息，用户ID：{}，预约ID：{}", appointment.getUserId(), appointment.getId());
        }
    }

    @Override
    public Result<String> startUse(int appointmentId) {
        try {

            ParkingAppointments appointments = parkingAppointmentsMapper.selectById(appointmentId);
            Date appointmentStart = appointments.getStartTime();
            Date appointmentEnd = appointments.getEndTime();
            Date now = new Date();
            boolean isWithinAppointment =
                    appointmentStart != null &&
                            appointmentEnd != null &&
                            !now.before(appointmentStart) && // 当前时间 >= 开始时间
                            !now.after(appointmentEnd);
            if(isWithinAppointment){
            appointments.setAppointmentStatus(ParkingAppointments.USING);
            parkingAppointmentsMapper.updateById(appointments);
            LambdaQueryWrapper<ParkingSpaces> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ParkingSpaces::getParkingLotId, appointments.getParkingLotId())
                    .eq(ParkingSpaces::getSpaceNumber, appointments.getSpaceNum());

// 执行查询
            ParkingSpaces spaces = parkingSpacesMapper.selectOne(queryWrapper);
            spaces.setSpaceStatus(ParkingSpaces.USEING);
            parkingSpacesMapper.updateById(spaces );
            return Result.success("开始使用");
            }
            else{
                return Result.error("开始使用失败！当前时间不在预约时间段之内！");
            }

        }catch (Exception e){
            log.error("orderParking has a error appointmentId={}", appointmentId, e);
            return Result.error("获取停车场信息失败！");
        }
    }

    @Override
    public Result<List<AppointmentListRes>> getAppointmentList(Integer userId) {
        try {

            LambdaQueryWrapper<ParkingAppointments> appointQuery = new LambdaQueryWrapper<>();
            appointQuery.eq(ParkingAppointments::getUserId, userId)
                            .orderByDesc(ParkingAppointments::getUpdatedAt);
            List<ParkingAppointments> parkingAppointments = parkingAppointmentsMapper.selectList(appointQuery);
            // 若无预约记录，直接返回空列表
            if (CollectionUtils.isEmpty(parkingAppointments)) {
                return Result.success(Collections.emptyList());
            }

            List<Integer> lotIds = parkingAppointments.stream().distinct().map(ParkingAppointments::getParkingLotId).collect(Collectors.toList());
            LambdaQueryWrapper<ParkingLots> lotQuery = new LambdaQueryWrapper<>();
            lotQuery.in(ParkingLots::getId, lotIds);
            List<ParkingLots> parkingLots = parkingLotsMapper.selectList(lotQuery);
            Map<Integer, ParkingLots> lotIdLotMap = parkingLots.stream()
                    .collect(Collectors.toMap(ParkingLots::getId, Function.identity(), (v1, v2) -> v1));


            List<AppointmentListRes> appointmentListResList = parkingAppointments.stream().map(appoint -> {
                AppointmentListRes res = new AppointmentListRes();
                res.setTitle(lotIdLotMap.get(appoint.getParkingLotId()).getParkingLotName());
                String start = DateUtils.formatTime(appoint.getStartTime());
                String end = DateUtils.formatTime(appoint.getEndTime());
                res.setAppointTimeStr(start + "--" + end);
                res.setSpaceNum(appoint.getSpaceNum());
                res.setTag(appoint.getAppointmentStatus().toString());
                res.setAppointmentId(appoint.getId());
                return res;
            }).collect(Collectors.toList());

            return Result.success(appointmentListResList);
        }catch (Exception e){
            log.error("orderParking has a error", e);
            return Result.error("获取停车场预约信息失败！");
        }
    }

    @Override
    public Result<ParkingFeeRes> getFee(int appointId) {
        try {
            ParkingAppointments appointments = parkingAppointmentsMapper.selectById(appointId);
            ParkingFeeRes fee = new ParkingFeeRes();
            fee.setStartTime(DateUtils.formatTime(appointments.getStartTime()));
            String parkingTime = calculateHoursAndMinutes(appointments.getStartTime(),new Date());
            fee.setParkingTime(parkingTime);

            int hours = (int)calculateHours(appointments.getStartTime(),new Date());
            ParkingLots parkingLots = parkingLotsMapper.selectById(appointments.getParkingLotId());
            Integer price = parkingLots.getPrice();

           if(appointments.getAppointmentStatus()== ParkingAppointments.OVERDUE_UNUSED){
               fee.setMsg("由于您预约未使用，请支付！");
           }else{
               fee.setMsg("使用情况正常，请支付！");
           }
            fee.setPrice(price * hours);

            return Result.success(fee);

        }catch (Exception e){
            log.error("getFee has a error", e);
            return Result.error("计算费用信息失败！");
        }
    }




    public static String calculateHoursAndMinutes(Date startDate, Date endDate) {
        // 确保结束时间大于开始时间
        if (endDate.before(startDate)) {
            throw new IllegalArgumentException("End time cannot be before start time.");
        }

        // 获取时间戳
        long startTimestamp = startDate.getTime();
        long endTimestamp = endDate.getTime();

        // 计算时间差，单位是毫秒
        long differenceInMillis = endTimestamp - startTimestamp;

        // 计算总的小时数
        long totalHours = differenceInMillis / (1000 * 60 * 60);

        // 如果不足一小时，按一小时计算
        if (differenceInMillis % (1000 * 60 * 60) != 0) {
            totalHours += 1;
        }

        // 计算剩余的分钟数
        long remainingMillis = differenceInMillis % (1000 * 60 * 60);
        long totalMinutes = remainingMillis / (1000 * 60);

        // 返回结果，格式化为 "小时:分钟"
        return totalHours + "小时" + totalMinutes + "分钟";
    }


    /**
     * 计算两个时间点之间的小时数，不足一小时按一小时计算
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 小时数（向上取整）
     */
    public static long calculateHours(Date startTime, Date endTime) {
        System.out.println(startTime);
        System.out.println(endTime);
        if (startTime == null || endTime == null) {
            throw new IllegalArgumentException("开始时间和结束时间不能为空");
        }

        if (startTime.after(endTime)) {
            throw new IllegalArgumentException("开始时间不能晚于结束时间");
        }

        // 计算时间差（毫秒）
        long durationMillis = endTime.getTime() - startTime.getTime();

        // 转换为小时（向上取整）
        // 1小时 = 60分钟 * 60秒 * 1000毫秒 = 3,600,000毫秒
        return (durationMillis + 3_599_999) / 3_600_000;
    }



    @Override
    public Result<String> leaveParking(int appointId) {
       try {
           ParkingAppointments appointments = parkingAppointmentsMapper.selectById(appointId);
           appointments.setAppointmentStatus(ParkingAppointments.WILL_PAY);
           appointments.setUpdatedAt(new Date());
           parkingAppointmentsMapper.updateById(appointments);
           LambdaQueryWrapper<ParkingSpaces> queryWrapper = new LambdaQueryWrapper<>();
           queryWrapper.eq(ParkingSpaces::getParkingLotId, appointments.getParkingLotId())
                   .eq(ParkingSpaces::getSpaceNumber, appointments.getSpaceNum());

// 执行查询
           ParkingSpaces spaces = parkingSpacesMapper.selectOne(queryWrapper);
           spaces.setSpaceStatus(ParkingSpaces.FREE);
           ParkingLots parkingLot = parkingLotsMapper.selectById(spaces.getParkingLotId());
           parkingLot.setLeftCount(parkingLot.getLeftCount()+1);
           parkingLotsMapper.updateById(parkingLot);
           parkingSpacesMapper.updateById(spaces );
           return Result.success("离场成功");

       }catch (Exception e){
           log.error("leaveParking has a error", e);
           return Result.error("离场失败！");
       }
    }

    @Override
    public Result<ParkingNeedPayFeeRes> getFeeDetail(int appointId) {
        try {

            ParkingAppointments appointments = parkingAppointmentsMapper.selectById(appointId);
            String appointmentNumber = appointments.getAppointmentNumber();

            ParkingFees fees = new ParkingFees();
            // 确定计算费用的时间范围
            Date calculateStartTime = appointments.getStartTime();
            Date calculateEndTime;

            // 判断是否为逾期未使用订单（根据实际状态常量调整）
            if (ParkingAppointments.OVERDUE_UNUSED==(appointments.getAppointmentStatus())) {
                // 逾期未使用：按预约的结束时间计算
                calculateEndTime = appointments.getEndTime();
                fees.setEndTime(calculateEndTime); // 记录预约结束时间作为费用计算终点
            } else {
                // 正常使用：按实际更新时间计算
                calculateEndTime = appointments.getUpdatedAt();
                fees.setEndTime(calculateEndTime); // 记录实际更新时间作为费用计算终点
            }
            fees.setAppointmentId(appointId);
            fees.setStartTime(appointments.getStartTime());
            fees.setEndTime(calculateEndTime);
            fees.setPaymentStatus(ParkingFees.PAY_STATUS_NO);
            fees.setCreatedAt(new Date());

            int hours = (int)calculateHours(calculateStartTime, calculateEndTime);

            Integer parkingLotId = appointments.getParkingLotId();
            ParkingLots parkingLots = parkingLotsMapper.selectById(parkingLotId);
            int price = parkingLots.getPrice();

            int totalFee = (price * hours);
            BigDecimal bigDecimalValue = BigDecimal.valueOf(totalFee);

            // 保留两位小数，使用 RoundingMode.HALF_UP 来进行四舍五入
            BigDecimal totalFeeBig = bigDecimalValue.setScale(2, RoundingMode.HALF_UP);

            fees.setTotalFee(totalFeeBig);
            LambdaQueryWrapper<ParkingFees>  feesjsonquery = new LambdaQueryWrapper<>();
            feesjsonquery.eq( ParkingFees::getAppointmentId, appointments.getId());
            ParkingFees existingFees = parkingFeesMapper.selectOne(feesjsonquery);
            if (existingFees == null) {
                parkingFeesMapper.insert(fees); // 不存在则插入
            }
            ParkingNeedPayFeeRes res = new ParkingNeedPayFeeRes();
            res.setParkingFeeId(existingFees==null?fees.getId():existingFees.getId());
            res.setTotalFee(totalFeeBig.toString());
            res.setParkingTimeStr(calculateHoursAndMinutes(appointments.getStartTime(),appointments.getUpdatedAt()));
            res.setAppointNum(appointmentNumber);
            res.setCreateTimeStr(DateUtils.formatTime(fees.getCreatedAt()));

            return Result.success(res);
        }catch (Exception e){
            log.error("getFeeDetail has a error", e);
            return Result.error("获取支付详情失败！");
        }
    }

    @Override
    public Result<String> payParkingFee(int parkingFeeId,int appointmentId) {
        try {

            ParkingAppointments appointment = parkingAppointmentsMapper.selectById(appointmentId);
            ParkingFees parkingFees = parkingFeesMapper.selectById(parkingFeeId);
            parkingFees.setPaymentStatus(ParkingFees.PAY_STATUS_HAS);
            parkingFeesMapper.updateById(parkingFees);
            MqTransmissionJson json=new MqTransmissionJson();
            json.setUuid(appointment.getId().toString()+"parking");
            json.setUserId(appointment.getUserId());
            json.setServiceType(ServiceType_ConvenientParking);
            if(appointment.getAppointmentStatus()==ParkingAppointments.OVERDUE_UNUSED){
                Date updatedAt = appointment.getCreatedAt();
                Date date = new Date();
                Instant updatedAtInstant = updatedAt.toInstant();
                Instant currentInstant = date.toInstant();
// 计算时间差
                Duration duration = Duration.between(updatedAtInstant, currentInstant);

                Long days = 0L;
// 获取时间差（天数）
                days = duration.toDays();
                json.setOverdue(true);
                LambdaQueryWrapper<Transmissionjson> transmissionjsonquery = new LambdaQueryWrapper<>();
                    transmissionjsonquery.eq(Transmissionjson::getUuid,  appointment.getId().toString()+"parking");
                    Transmissionjson transmissionjson=transmissionjsonMapper.selectOne(transmissionjsonquery);
                    json.setDueTime(transmissionjson.getDueTime().toInstant());
                if (days <= 7) {
                    json.setOverduePeriod(1); // 1-7天为第1档
                } else if (days <= 14) {
                    json.setOverduePeriod(2); // 8-14天为第2档
                } else if (days <= 90) {
                    json.setOverduePeriod(3); // 15天-3个月为第3档
                } else {
                    json.setOverduePeriod(4); // 超过3个月归为第4档
                }
            }else{
                json.setOverdue(false);
                json.setOverduePeriod(-1);
                json.setDueTime(null);
            }
            json.setPaid(true);
            json.setAmount(parkingFees.getTotalFee().doubleValue());
            json.setFinishTime(Instant.now());
            json.setDesc("便捷停车信用分计算");
            kafkaProducerService.sendJsonMessage(json);
            appointment.setAppointmentStatus(ParkingAppointments.DONE);
            parkingAppointmentsMapper.updateById(appointment);
            return Result.success("支付成功！");
        }catch (Exception e){
            log.error("payParkingFee has a error parkingFeeId={}",parkingFeeId, e);
            return Result.error("支付失败！");
        }
    }

    @Override
    public Result<ParkingLotPageRes> getAdminParkingLot(int pageNum, int pageSize, int type, String title) {
       try {

           ParkingLotPageRes res = new ParkingLotPageRes();

           LambdaQueryWrapper<ParkingLots> lotQuery = new LambdaQueryWrapper<>();
           lotQuery.eq(type != 0 , ParkingLots::getParkingLotType, type)
                   .like(!title.equals(""), ParkingLots::getParkingLotName, title)
                   .orderByDesc(ParkingLots::getUpdatedAt);

           Page<ParkingLots> page = new Page<>(pageNum,pageSize);
           Page<ParkingLots> lotsPage = parkingLotsMapper.selectPage(page, lotQuery);

           res.setParkingLotsList(lotsPage.getRecords());
           res.setTotal(lotsPage.getTotal());

           return Result.success(res);

       }catch (Exception e){
           log.error("getAdminParkingLot has a error", e);
           return Result.error("获取失败！");
       }
    }

    @Override
    public Result<String> deletedParkLot(int parkingLotId) {
        try {

            int res = parkingLotsMapper.deleteById(parkingLotId);
            if (res <= 0){

                return Result.error("删除失败！");
            }
            return Result.success("删除成功！");

        }catch (Exception e){
            log.error("deletedParkLot has a error", e);
            return Result.error("删除失败！");
        }
    }
    @Override
    public Result<String> saveparkingLot(ParkingLots parkingLots ) {
        try {

            parkingLotsMapper.insert(parkingLots);
            return Result.success("添加成功！");
        } catch (Exception e) {
            log.error("saveBook has a error", e);
            return Result.error("添加失败！");
        }
    }
    @Override
    public Result<String> updateParkingLot(ParkingLots parkingLots ) {
        try {

            parkingLotsMapper.updateById(parkingLots);
            return Result.success("修改成功！");

        }catch (Exception e){
            log.error("updateParkingLot has a error", e);
            return Result.error("编辑失败！");
        }

    }

    @Override
    public Result<String> getScore(Integer userId) {
        try {


            CreditScore creditScore = creditScoreMapper.selectById(userId);
            return Result.success(creditScore.getScore().toString());

        }catch (Exception e){
            log.error("getScore has a error", e);
            return Result.error("获取失败！");
        }
    }



}
